/*
 * Copyright 2008 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.ccsoft.mc.core.impl;

import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.ccsoft.mc.core.Property;
import org.ccsoft.mc.core.Reference;
import org.ccsoft.mc.core.ServiceBundle;
import org.ccsoft.mc.core.exceptions.LoadConfigException;
import org.ccsoft.mc.core.exceptions.SetRefereceException;
/**
 * 
 * @author Chao Cai
 *
 */
public class BundleUtil {
	/*public static final int READY=0;
	public static final int =0;
	public static final int UNRESOLVED=2;*/
	public BundleUtil() {
		super();
		// TODO Auto-generated constructor stub
	}
	private static String covertMethodName(String methodName){
		String firstLetter=methodName.substring(0,1).toUpperCase();
		String lastPart=methodName.substring(1);
		String name=firstLetter+lastPart;
		return name;
	}
	private static void setReference(Object obj,Reference ref,Object serviceIns){
		Class c=obj.getClass();		
		Method [] methods=c.getMethods();
		String setMethodName="set"+covertMethodName(ref.getProperty());
		for (Method method:methods){			
			if (method.getName().equals(setMethodName)){
				try {
					method.invoke(obj,new Object[]{serviceIns});
					break;
				} catch (Exception e) {
					throw new SetRefereceException(e);
				} 
			}
		}
	}
	private static Object createPropertyValueObject(String value,Method method){
		Object ret=null;
		String type=method.getParameterTypes()[0].getName();
		if(value!=null && !value.equals("")) {      
            if(type.equals("java.lang.String")) {
            	ret=value;           
            }
            else if(type.equals("int") || type.equals("java.lang.Integer")) {
            	ret=new Integer(value);            	
            }
            else if(type.equals("long") || type.equals("java.lang.Long")) {
            	ret = new Long(value);            
            }
            else if(type.equals("boolean") || type.equals("java.lang.Boolean")) {
            	ret=Boolean.valueOf(value);            	
            }
            else if(type.equals("java.util.Date")) {
              SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
              Date date;
			try {
				date = format.parse(value);
			} catch (ParseException e) {
				throw new LoadConfigException(e);
			}
              ret= date;
            }
          }
		return ret;	

	}	
	public  static void setProperty(Object obj,Property pro){
		Class c=obj.getClass();		
		Method [] methods=c.getMethods();
		String setMethodName="set"+covertMethodName(pro.getName());
		for (Method method:methods){			
			if (method.getName().equals(setMethodName)){
				try {
					Object valueObject=createPropertyValueObject((String)pro.getValue(),method);
					method.invoke(obj,new Object[]{valueObject});
				} catch (Exception e) {
					throw new SetRefereceException(e);
				} 
			}
		}
	}
	public static boolean isAllReferenceAvailable(ServiceBundle bundle,BaseCache readyServiceCache){		
		List<Reference> refs= bundle.getReferences();		
		for (Reference ref:refs){
			Object service=readyServiceCache.getServiceByType(ref.getInterfaceName());
			if  (service==null){
				return false;				
			}
		}
		return true;
	}
	/**
	 * 
	 * @param bundle
	 * @return the true value means all the references of the bundle have been injected
	 */	
	public static  void injectReference(ServiceBundle bundle,BaseCache readyServiceCache){		
	/*	if (BundleUtil.isAllReferenceAvailable(bundle,readyServiceCache))*/{
			List<Reference> refs=bundle.getReferences();
			for (Reference ref:refs){
				Object serviceIns=null;
				//-1 means n
				if (ref.getCardinalityMax()==-1){
					serviceIns=readyServiceCache.getServicesByType(ref.getInterfaceName());	
					setReference(bundle.getInstance(),ref,serviceIns);
					continue;
				}
				if (ref.getComponentName()==null||ref.getComponentName()==""){
					serviceIns=readyServiceCache.getServiceByType(ref.getInterfaceName());
				}else{
					serviceIns=readyServiceCache.getServiceByType(ref.getInterfaceName(),ref.getComponentName());
				}
				setReference(bundle.getInstance(),ref,serviceIns);
			}
			readyServiceCache.add(bundle);
		}
	}

}
